wayland: Add support for xdg_toplevel.bounds
authorJonas Ådahl <jadahl@gmail.com>
Tue, 4 Aug 2020 14:52:20 +0000 (16:52 +0200)
committerJonas Ådahl <jadahl@gmail.com>
Mon, 13 Jun 2022 20:12:55 +0000 (22:12 +0200)
The GdkToplevelSize struct already has the concept of "bounds", which
means the largest size a window should reasonably have. It's practically
the equivalent of the monitor the window is intended to be mapped on,
with the "struts" (e.g. panels) cut out. It's used by GTK to use this
information to calculate a default window size that is "lagom" (swedish;
not too large, not too small).

gdk/wayland/gdkdisplay-wayland.c
gdk/wayland/gdksurface-wayland.c
meson.build

index 64d61a8983fbd775741bd01e2d7dc2a1cbc5fca2..9079c6ddd3d82b9108fef3ca01adcc3477551244 100644 (file)
@@ -623,7 +623,7 @@ _gdk_wayland_display_open (const char *display_name)
         wl_registry_bind (display_wayland->wl_registry,
                           display_wayland->xdg_wm_base_id,
                           &xdg_wm_base_interface,
-                          MIN (display_wayland->xdg_wm_base_version, 3));
+                          MIN (display_wayland->xdg_wm_base_version, 4));
       xdg_wm_base_add_listener (display_wayland->xdg_wm_base,
                                 &xdg_wm_base_listener,
                                 display_wayland);
index 0b3315075ec233d51c9aa6b05d10591eebea5493..d35ffb229986453d43a175da91c4de2f72cae9e6 100644 (file)
@@ -168,6 +168,10 @@ struct _GdkWaylandSurface
 
   struct {
     GdkToplevelLayout *layout;
+
+    int bounds_width;
+    int bounds_height;
+    gboolean has_bounds;
   } toplevel;
 
   struct {
@@ -182,6 +186,10 @@ struct _GdkWaylandSurface
       int height;
       GdkToplevelState state;
       gboolean is_resizing;
+
+      int bounds_width;
+      int bounds_height;
+      gboolean has_bounds;
     } toplevel;
 
     struct {
@@ -1394,19 +1402,28 @@ configure_toplevel_geometry (GdkSurface *surface)
 {
   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
   GdkDisplay *display = gdk_surface_get_display (surface);
-  GdkMonitor *monitor;
-  GdkRectangle monitor_geometry;
   int bounds_width, bounds_height;
   GdkToplevelSize size;
   GdkToplevelLayout *layout;
   GdkGeometry geometry;
   GdkSurfaceHints mask;
 
-  monitor = g_list_model_get_item (gdk_display_get_monitors (display), 0);
-  gdk_monitor_get_geometry (monitor, &monitor_geometry);
-  g_object_unref (monitor);
-  bounds_width = monitor_geometry.width;
-  bounds_height = monitor_geometry.height;
+  if (impl->toplevel.has_bounds)
+    {
+      bounds_width = impl->toplevel.bounds_width;
+      bounds_height = impl->toplevel.bounds_height;
+    }
+  else
+    {
+      GdkMonitor *monitor;
+      GdkRectangle monitor_geometry;
+
+      monitor = g_list_model_get_item (gdk_display_get_monitors (display), 0);
+      gdk_monitor_get_geometry (monitor, &monitor_geometry);
+      bounds_width = monitor_geometry.width;
+      bounds_height = monitor_geometry.height;
+      g_object_unref (monitor);
+    }
 
   gdk_toplevel_size_init (&size, bounds_width, bounds_height);
   gdk_toplevel_notify_compute_size (GDK_TOPLEVEL (surface), &size);
@@ -1508,6 +1525,13 @@ gdk_wayland_surface_configure_toplevel (GdkSurface *surface)
   is_resizing = impl->pending.toplevel.is_resizing;
   impl->pending.toplevel.is_resizing = FALSE;
 
+  if (impl->pending.toplevel.has_bounds)
+    {
+      impl->toplevel.bounds_width = impl->pending.toplevel.bounds_width;
+      impl->toplevel.bounds_height = impl->pending.toplevel.bounds_height;
+      impl->toplevel.has_bounds = TRUE;
+    }
+
   fixed_size =
     new_state & (GDK_TOPLEVEL_STATE_MAXIMIZED |
                  GDK_TOPLEVEL_STATE_FULLSCREEN |
@@ -1847,9 +1871,24 @@ xdg_toplevel_close (void                *data,
   gdk_wayland_surface_handle_close (surface);
 }
 
+static void
+xdg_toplevel_configure_bounds (void                *data,
+                               struct xdg_toplevel *xdg_toplevel,
+                               int32_t              width,
+                               int32_t              height)
+{
+  GdkSurface *surface = GDK_SURFACE (data);
+  GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
+
+  impl->pending.toplevel.bounds_width = width;
+  impl->pending.toplevel.bounds_height = height;
+  impl->pending.toplevel.has_bounds = TRUE;
+}
+
 static const struct xdg_toplevel_listener xdg_toplevel_listener = {
   xdg_toplevel_configure,
   xdg_toplevel_close,
+  xdg_toplevel_configure_bounds,
 };
 
 static void
index b7a6cb742fa6f8c457e51a8fd05f47731d970b0e..896a1bba60139fb03a95c795915aadd0809ddd1b 100644 (file)
@@ -17,7 +17,7 @@ fribidi_req        = '>= 0.19.7'
 cairo_req          = '>= 1.14.0'
 gdk_pixbuf_req     = '>= 2.30.0'
 introspection_req  = '>= 1.39.0'
-wayland_proto_req  = '>= 1.23'
+wayland_proto_req  = '>= 1.25'
 wayland_req        = '>= 1.20.0'
 graphene_req       = '>= 1.9.1'
 epoxy_req          = '>= 1.4'